package ext.trace.scene;

import ext.trace.geom.Geom;
import java.util.ArrayList;
import math.math;
import math.region.Ray3;
import math.region.Surface3;

public class SceneNSq extends Scene
{
    
    public ArrayList<Geom> mGeom;
    
    
    public SceneNSq()
    {
        this.mGeom = new ArrayList<>();
    }
    
    
    public void add(final Geom geom)
    {
        super.add(geom);
        this.mGeom.add(geom);
    }
    
    
    public double castOcclusion(
            Ray3 aRay, 
            Geom aTarget, 
            double time)
    {
        double minT = Double.MAX_VALUE;
        Geom minGeom = null;
        for (int i = 0; i < this.mGeom.size(); i++)
        {
            Geom g = this.mGeom.get(i);
            Surface3 surf = g.lerp(time);
            double t = this.intersectSurface(surf, aRay);
            boolean validT = (t > math.EPSILON && t < Double.MAX_VALUE);
            boolean betterT = (t < minT);
            if (validT && betterT)
            {
                minT = t;
                minGeom = g;
            }
        }
        if (minGeom != null && minGeom.equals(aTarget))
        {
            return 1.0;
        }
        return 0.0;
    }
    
    
    public Hit castRay(Ray3 aRay, double time)
    {
        Hit hit = new Hit();
        hit.mT = Double.MAX_VALUE;
        for (int i = 0; i < this.mGeom.size(); i++)
        {
            Geom g = this.mGeom.get(i);
            Surface3 surf = g.lerp(time);
            double t = this.intersectSurface(surf, aRay);
            boolean validT = (t > math.EPSILON && t < Double.MAX_VALUE);
            boolean betterT = (t < hit.mT);
            if (validT && betterT)
            {
                hit.mT = t;
                hit.rPt = aRay.point(hit.mT);
                hit.rUV = surf.convertWorld_Param(hit.rPt);
                hit.rNorm = surf.surfaceNorm(hit.rPt, aRay.mOrig);
                hit.rColor = g.mMat.rBRDF.rAlbedo.lookupNN(hit.rUV);
                hit.rMat = g.mMat;
                hit.rSurface = surf;
            }
        }
        if (hit.rPt == null)
        {
            return null;
        }
        return hit;
    }
    
    
}
